using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Windows.Forms;
using System.ComponentModel;
using SharedUtils;
using System.IO;
using System.Threading;

namespace SceneEditor
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    [DesignTimeVisibleAttribute]
    [ToolboxItemAttribute(true)]
    public class ShaderGraph : GraphicsDeviceControl
    {
        public static SpriteBatch spriteBatch;
        public static ContentManager content;
        public SceneEditorForm form;
        Camera2d cam;

        Texture2D camera_tex, sound_tex;

        public ShaderGraph()
        {
            
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            content = new ContentManager(Services, "Content");
            spriteBatch = new SpriteBatch(GraphicsDevice);

            LoadContent(content);
            
            // Hook the idle event to constantly redraw our animation.
            Application.Idle += delegate { Invalidate(); };
        }

        public void ReInitialize()
        {

        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected void LoadContent(ContentManager content)
        {
            cam = new Camera2d();
            
            camera_tex = PictureEntity.GetTextureFromStream(GraphicsDevice, @"C:\Program Files\PictureSense\Content\camera.png");
            sound_tex = PictureEntity.GetTextureFromStream(GraphicsDevice, @"C:\Program Files\PictureSense\Content\sound.png");
        }

        public void Update()
        {
            SetCameraRectColor();

            foreach (var item in SceneEditorForm.util.entities)
            {
                if (item is PictureEntity)
                {
                    PictureEntity pe = (PictureEntity)item;
                    if(pe.picture == null)
                    {
                        pe.picture = PictureEntity.GetTextureFromStream(GraphicsDevice, pe.picturePath);
                        if (pe.picture == null)
                        {
                            MessageBox.Show("Error loading file!");
                        }
                    }
                }
            }

            HandleInput();
            
        }

        MouseState oldMouse = new MouseState();
        Vector2 mouseLocationForConnect;
        public void HandleInput()
        {
            MouseState mouse = Mouse.GetState();
            KeyboardState keyboard = Keyboard.GetState();
            float speed = 0.05f;

            if(keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.A))
            {
                if(SceneEditorForm.selected_entity != null)
                {
                    SceneEditorForm.selected_entity.position = new Vector2(SceneEditorForm.selected_entity.position.X - speed, SceneEditorForm.selected_entity.position.Y);
                }
                if (SceneEditorForm.selected_camera != null)
                {
                    SceneEditorForm.selected_camera._pos = new Vector2(SceneEditorForm.selected_camera._pos.X - speed, SceneEditorForm.selected_camera._pos.Y);
                }
            }

            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.D))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    SceneEditorForm.selected_entity.position = new Vector2(SceneEditorForm.selected_entity.position.X + speed, SceneEditorForm.selected_entity.position.Y);
                }
                if (SceneEditorForm.selected_camera != null)
                {
                    SceneEditorForm.selected_camera._pos = new Vector2(SceneEditorForm.selected_camera._pos.X + speed, SceneEditorForm.selected_camera._pos.Y);
                }
            }

            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.W))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    SceneEditorForm.selected_entity.position = new Vector2(SceneEditorForm.selected_entity.position.X, SceneEditorForm.selected_entity.position.Y - speed);
                }
                if (SceneEditorForm.selected_camera != null)
                {
                    SceneEditorForm.selected_camera._pos = new Vector2(SceneEditorForm.selected_camera._pos.X, SceneEditorForm.selected_camera._pos.Y - speed);
                }
            }

            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.S))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    SceneEditorForm.selected_entity.position = new Vector2(SceneEditorForm.selected_entity.position.X, SceneEditorForm.selected_entity.position.Y + speed);
                }
                if (SceneEditorForm.selected_camera != null)
                {
                    SceneEditorForm.selected_camera._pos = new Vector2(SceneEditorForm.selected_camera._pos.X, SceneEditorForm.selected_camera._pos.Y + speed);
                }
            }

            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.R))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    if(SceneEditorForm.selected_entity is PictureEntity)
                    {
                        PictureEntity pe = (PictureEntity)SceneEditorForm.selected_entity;
                        pe.rotation = pe.rotation + 0.0005f;
                    } 
                }
            }

            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.T))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    if(SceneEditorForm.selected_entity is PictureEntity)
                    {
                        PictureEntity pe = (PictureEntity)SceneEditorForm.selected_entity;
                        pe.rotation = pe.rotation - 0.0005f;
                    }
                    
                }
            }

            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.F))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    if(SceneEditorForm.selected_entity is PictureEntity)
                    {
                        PictureEntity pe = (PictureEntity)SceneEditorForm.selected_entity;
                        pe.pictureSize = new Vector2(pe.pictureSize.X + 0.0001f, 0.0f);
                    } 
                }

                if (SceneEditorForm.selected_camera != null)
                {
                    SceneEditorForm.selected_camera.Zoom += 0.0001f;
                }
            }


            if (keyboard.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.G))
            {
                if (SceneEditorForm.selected_entity != null)
                {
                    if(SceneEditorForm.selected_entity is PictureEntity)
                    {
                        PictureEntity pe = (PictureEntity)SceneEditorForm.selected_entity;
                        pe.pictureSize = new Vector2(pe.pictureSize.X - 0.0001f, 0.0f);
                    }
                }

                if (SceneEditorForm.selected_camera != null)
                {
                    SceneEditorForm.selected_camera.Zoom -= 0.0001f;
                }
            }


            //Handle Camera Movements
            Vector2 mouseLocation = new Vector2(mouse.X,mouse.Y);
            Vector2 oldMouseLocation = new Vector2(oldMouse.X, oldMouse.Y);
            if(mouse.MiddleButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed){
                cam._pos += (oldMouseLocation - mouseLocation);
            }

            if(mouse.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed){
                if(mouseLocationForConnect == null)
                    mouseLocationForConnect = new Vector2(mouse.X,mouse.Y);

            }

            #region Zoom
            //Handle Zoom
            if(mouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed){
                Vector2 value = (oldMouseLocation - mouseLocation);
                if(value.Length() != 0){
                    value.Normalize();
                    value *= 0.01f;
                    cam.Zoom += value.X;
                }
            }
            #endregion
            oldMouse = mouse;
        }

        private bool checkForBounds(Vector2 v1, Vector2 v2, Texture2D t)
        {
            Rectangle r = new Rectangle((int)v2.X,(int)v2.Y,(int)t.Width,(int)t.Height);
            return r.Contains(new Point((int)v1.X,(int)v1.Y));
        }

        public void SetCameraRectColor()
        {
            System.Drawing.Color c = SceneEditorForm.g_BackgroundColor;
            SceneEditorForm.g_CameraRectColor = System.Drawing.Color.FromArgb(100, (byte)255 - c.R , (byte)255 - c.G, (byte)255 - c.B);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw()
        {
            Update();

            System.Drawing.Color background = SceneEditor.SceneEditorForm.g_BackgroundColor;
            Microsoft.Xna.Framework.Color newBackgroundColor = new Microsoft.Xna.Framework.Color(background.R, background.G, background.B, background.A);
            GraphicsDevice.Clear(newBackgroundColor);

            // if using XNA 4.0
            spriteBatch.Begin(SpriteSortMode.BackToFront,
                            BlendState.AlphaBlend,
                            null,
                            null,
                            null,
                            null,
                            cam.get_transformation(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height));
            
            foreach (var item in SceneEditorForm.util.entities)
            {
                if(item is PictureEntity)
                {
                    PictureEntity pe = (PictureEntity)item;
                    if(pe.isVisible && pe.picture != null)
                    {
                        spriteBatch.Draw(pe.picture, pe.position, null, Color.White, pe.rotation,
                                Vector2.Zero, pe.pictureSize.X, SpriteEffects.None, 0f);
                    }
                }
                else if(item is SoundEntity)
                {
                    SoundEntity se = (SoundEntity)item;
                    if(se.isVisible)
                    {
                        spriteBatch.Draw(sound_tex, se.position, null, Color.White);
                    }
                }
                
            }

            foreach (var item in SceneEditorForm.util.cameras)
            {
                //Draw the camera
                spriteBatch.Draw(camera_tex, item._pos, null, Color.White);
                
                //Draw the Camera Rectangle
                var t = new Texture2D(GraphicsDevice, 1, 1);
                t.SetData(new[] { Color.White });

                Rectangle r = new Rectangle();
                Matrix m = cam.get_transformation(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

                Microsoft.Xna.Framework.Color c = new Microsoft.Xna.Framework.Color(SceneEditorForm.g_CameraRectColor.R,
                                                                                    SceneEditorForm.g_CameraRectColor.G,
                                                                                    SceneEditorForm.g_CameraRectColor.B,
                                                                                    SceneEditorForm.g_CameraRectColor.A);
                spriteBatch.Draw(t, r, c);
            }
            spriteBatch.End();
        }
    }
}
